
package com.bei_en.teacher.third.pay.web.Mwxpay;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ConnectException;
import java.net.URL;
import java.net.URLConnection;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import org.apache.log4j.Logger;
import com.bei_en.teacher.third.pay.bean.Mwxpay.AccessToken;
import com.bei_en.teacher.third.pay.bean.Mwxpay.JsTicket;
import com.google.gson.Gson;

/**
 * 微信通用接口工具类
 * 
 * @author txw
 * @version 1.0
 * 
 */
public class WeixinUtil {

    public static Logger log = Logger.getLogger(WeixinUtil.class);

    /**
     * 获取access_token的接口地址（GET） 限200（次/天）
     */
    public final static String ACCESS_TOKEN = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
    public final static String GET_JSAPI_TICKET = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi";

    private static long lastTime1 = System.currentTimeMillis()-7001*1000;
    private static long lastTime2 = System.currentTimeMillis()-7001*1000;
    public static SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    private static String token;
    private static String ticket;

    public static String getToken(String appid, String appsecret, boolean doRefresh) {

	long currentTime = System.currentTimeMillis();
	String last = format.format(new Date(lastTime1));
	String current = format.format(new Date(currentTime));
	if (currentTime-lastTime1>7000*1000||doRefresh) {
	    token = httpsRequest(
		    ACCESS_TOKEN.replace("APPID", appid).replace("APPSECRET", appsecret), "GET",
		    null, AccessToken.class).getAccess_token();
	    lastTime1 = currentTime;
	    log.info("token刷新了");
	} else {
	    log.info("token已使用"+(currentTime-lastTime1)/1000+"秒");
	}
	return token;
    }

    /**
     * 发起https请求并获取结果
     * 
     * @param requestUrl
     *            请求地址
     * @param requestMethod
     *            请求方式（GET、POST）
     * @param outputStr
     *            提交的数据
     * @return JSONObject(通过JSONObject.get(key)的方式获取json对象的属性值)
     */
    public static <T> T httpsRequest(String requestUrl, String requestMethod, String outputStr,
	    Class<T> type) {

	T jsonObject = null;
	StringBuffer buffer = new StringBuffer();
	try {
	    // 创建SSLContext对象，并使用我们指定的信任管理器初始化
	    TrustManager[] tm = { new MyX509TrustManager() };
	    SSLContext sslContext = SSLContext.getInstance("SSL");
	    sslContext.init(null, tm, new java.security.SecureRandom());
	    // 从上述SSLContext对象中得到SSLSocketFactory对象
	    SSLSocketFactory ssf = sslContext.getSocketFactory();

	    URL url = new URL(null, requestUrl, new sun.net.www.protocol.https.Handler());
	    HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection();
	    httpUrlConn.setSSLSocketFactory(ssf);

	    httpUrlConn.setDoOutput(true);
	    httpUrlConn.setDoInput(true);
	    httpUrlConn.setUseCaches(false);
	    // 设置请求方式（GET/POST）
	    httpUrlConn.setRequestMethod(requestMethod);

	    if ("GET".equalsIgnoreCase(requestMethod)) {
		httpUrlConn.connect();
	    }

	    // 当有数据需要提交时
	    if (null!=outputStr) {
		OutputStream outputStream = httpUrlConn.getOutputStream();
		// 注意编码格式，防止中文乱码
		outputStream.write(outputStr.getBytes("UTF-8"));
		outputStream.close();
	    }

	    // 将返回的输入流转换成字符串
	    InputStream inputStream = httpUrlConn.getInputStream();
	    InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
	    BufferedReader bufferedReader = new BufferedReader(inputStreamReader);

	    String str = null;
	    while ((str = bufferedReader.readLine())!=null) {
		buffer.append(str);
	    }
	    bufferedReader.close();
	    inputStreamReader.close();
	    // 释放资源
	    inputStream.close();
	    inputStream = null;
	    httpUrlConn.disconnect();
	    log.info(type+"=\n"+buffer.toString());
	    jsonObject = new Gson().fromJson(buffer.toString(), type);
	} catch (ConnectException ce) {
	    log.error("server connection timed out.");
	    System.out.println("--------------server connection timed out."+ce);
	} catch (Exception e) {
	    log.error("https request error:", e);
	    System.out.println("--------------server connection timed out."+e);
	}
	return jsonObject;
    }

    /**
     * 将微信消息中的CreateTime转换成标准格式的时间（yyyy-MM-dd HH:mm:ss）
     * 
     * @param createTime
     *            消息创建时间
     * @return String
     */
    public static String formatTime(String createTime) {

	// 将微信传入的CreateTime转换成long类型，再乘以1000
	long msgCreateTime = Long.parseLong(createTime)*1000L;
	DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
	return format.format(new Date(msgCreateTime));
    }

    /**
     * 发送POST请求，获取数据
     * 
     * @param url
     *            发送请求的URL
     * @param param
     *            请求参数 name1=value1&name2=value2
     */
    public static String sendPost(String url, String param) {

	PrintWriter out = null;
	BufferedReader in = null;
	String result = "";
	try {
	    URL realUrl = new URL(url);
	    URLConnection conn = realUrl.openConnection();
	    conn.setDoOutput(true);
	    conn.setDoInput(true);
	    out = new PrintWriter(conn.getOutputStream());
	    out.print(param);
	    out.flush();
	    in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
	    String line;
	    while ((line = in.readLine())!=null) {
		result += line;
	    }
	} catch (Exception e) {
	    log.error(e);
	} finally {
	    try {
		if (out!=null) {
		    out.close();
		}
		if (in!=null) {
		    in.close();
		}
	    } catch (IOException ex) {
		ex.printStackTrace();
	    }
	}
	return result;
    }

    /**
     * @author Guocg
     * @param appid
     * @param appsecret
     * @param token2
     * @param b
     * @return
     */
    public static String getJsApiTicket(String appid, String appsecret, String token2,
	    boolean doRefresh) {

	long currentTime = System.currentTimeMillis();
	String last = format.format(new Date(lastTime2));
	String current = format.format(new Date(currentTime));
	if (currentTime-lastTime2>7000*1000||doRefresh) {
	    ticket = httpsRequest(GET_JSAPI_TICKET.replace("ACCESS_TOKEN", token2), "GET", null,
		    JsTicket.class).getTicket();
	    lastTime2 = currentTime;
	    log.info("ticket刷新了");
	} else {
	    log.info("ticket已使用"+(currentTime-lastTime2)/1000+"秒");
	}
	return ticket;
    }

    public static void main(String[] args) {

	String token = getToken("wx54c54ddcf31f676c", "c4b857c3a9cd1ea94d743dd4fcf07002", false);
	System.out.println(token);
	String ticket = getJsApiTicket("wx54c54ddcf31f676c", "c4b857c3a9cd1ea94d743dd4fcf07002",
		token, false);
	System.out.println(ticket);

    }
}